//
//  BannerView.swift
//  EyeVisionForPatients
//
//  Created by PMC on 2020/3/9.
//  Copyright © 2020 tao Tao. All rights reserved.
//

import UIKit

protocol BannerViewDelegate: NSObjectProtocol {
    func bannerView(_ bannerView: BannerView, didSelectedItemWith viewModel: YSGBannerCellViewModel)
}

class BannerView: UIView {
    
    private override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupUI()
    }
    
    // 随父控件的消失取消定时器
    override func removeFromSuperview() {
        super.removeFromSuperview()
        timer?.invalidate()
        timer = nil
    }
    
    private var timer: Timer?
    
    weak var delegate: BannerViewDelegate?
    
    var imageUrls: [String]? {
        didSet {
            guard let urls = imageUrls, !urls.isEmpty else { return }
            
            if urls.count <= 1 {
                timer?.invalidate()
                timer = nil
                collectionView.isScrollEnabled = false
            }
            
            pageControl.numberOfPages = urls.count
            collectionView.reloadData()
            
            // 滚动到中间位置
            let centerIndexPath = IndexPath(item: urls.count * kCount, section: 0)
            collectionView.scrollToItem(at: centerIndexPath, at: .left, animated: false)
        }
    }
    
    var viewModel: YSGBannerViewModel? {
        didSet {
            guard let vm = viewModel else {
                collectionView.isScrollEnabled = false
                return
            }
            
            imageUrls = vm.models.map { $0.content ?? "" }.filter { !$0.isEmpty }
        }
    }
    
    private var placeHoldImage: UIImage?
    
    var isAutoScroll = false {
        didSet {
            if isAutoScroll { addTimer() }
        }
    }
    
    private let duration: TimeInterval = 2
    // CollectionView复用cell的机制,不管当前的section有道少了item
    // 当cell的宽和屏幕的宽一致是,当前屏幕最多显示两个cell(图片切换时是两个cell),切换完成时有且仅有一个cell
    // 即使放大1000倍,内存中最多加载两个cell,所以不会造成内存暴涨现象
    private let kCount = 100
    
    private lazy var collectionView: UICollectionView = {
        let layout = BannerFlowLayout()
        let collView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collView.bounces = false;
        collView.isPagingEnabled = true;
        collView.showsVerticalScrollIndicator = false;
        collView.showsHorizontalScrollIndicator = false;
        collView.dataSource = self
        collView.delegate = self
        collView.backgroundColor = .clear
        collView.register(BannerViewCell.self, forCellWithReuseIdentifier: BannerViewCell.reuseIdentifier)
        return collView
    }()
    
    private lazy var pageControl: UIPageControl = {
        let pageControl = UIPageControl()
        pageControl.isUserInteractionEnabled = false
        pageControl.pageIndicatorTintColor = .white
        pageControl.currentPageIndicatorTintColor = .splLineSelect
        pageControl.contentHorizontalAlignment = .center
        pageControl.hidesForSinglePage = true
        return pageControl
    }()
}

extension BannerView {
    func setupUI() {
        backgroundColor = .white
        layer.cornerRadius = 8
        clipsToBounds = true
        addSubview(collectionView)
        addSubview(pageControl)
        
        collectionView.snp.makeConstraints({ (make) in
            make.edges.equalToSuperview()
        })
        
        pageControl.snp.makeConstraints { (make) in
            make.left.right.bottom.equalToSuperview()
            make.height.equalTo(20)
        }
    }
    
    /// 添加定时器
    private func addTimer() {
        if timer == nil {
            timer = Timer.scheduledTimer(withTimeInterval: duration, repeats: true, block: { [weak self] (_) in
                self?.nextPage()
            })
        }
    }
    
    private func nextPage() {
        // 获取当前位置,滚动到下一位置
        guard let currentIndexPath = collectionView.indexPathsForVisibleItems.last else { return }
        let nextIndexPath = IndexPath(item: currentIndexPath.item + 1, section: currentIndexPath.section)
        collectionView.scrollToItem(at: nextIndexPath, at: .left, animated: true)
    }
}

extension BannerView: UICollectionViewDataSource, UICollectionViewDelegate {
    // MARK:- collection datasource
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return (imageUrls?.count ?? 0) * 2 * kCount
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BannerViewCell.reuseIdentifier,
                                                      for: indexPath) as! BannerViewCell
        cell.item = indexPath.item % (imageUrls?.count)!
        cell.imgUrl = imageUrls?[indexPath.item % (imageUrls?.count)!] ?? ""
        return cell
    }
    
    //MARK: - collectionViewDelegate
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) as? BannerViewCell, let vm = viewModel?.viewModel(at: cell.item) else { return }
        delegate?.bannerView(self, didSelectedItemWith: vm)
    }
    
    //MARK: - scrollView delegate
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let offsetX = scrollView.contentOffset.x
        var page = Int(offsetX / bounds.size.width + 0.5)
        page = page % (imageUrls?.count)!
        pageControl.currentPage = page
    }
    
    // 监听手动减速完成(停止滚动)  - 获取当前页码,滚动到下一页,如果当前页码是第一页,继续往下滚动,如果是最后一页回到第一页
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let offsetX = scrollView.contentOffset.x
        let page = Int(offsetX / bounds.size.width)
        let itemsCount = collectionView.numberOfItems(inSection: 0)
        
        if page == 0 { // 第一页
            let x = offsetX + CGFloat((imageUrls?.count)! * kCount) * bounds.size.width
            collectionView.setContentOffset(CGPoint(x: x, y: 0), animated: false)
        } else if page == itemsCount - 1 { // 最后一页
            let x = offsetX - CGFloat((imageUrls?.count)! * kCount) * bounds.size.width
            collectionView.setContentOffset(CGPoint(x: x, y: 0), animated: false)
        }
    }
    
    // 滚动动画结束的时候调用 - 获取当前页码,滚动到下一页,如果当前页码是第一页,继续往下滚动,如果是最后一页回到第一页
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        scrollViewDidEndDecelerating(scrollView)
    }
    
    // 当手动拖动开始时, 结束计时器
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        timer?.invalidate()
        timer = nil
    }
    // 当手动拖动结束后 开启计时器
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        addTimer()
    }
}
